//@version=5
indicator("CRT with HTF Boxes", overlay=true)

// Inputs
enable_crt_h1_check = input.bool(true, title="Turn on CRT H1 test?", tooltip="Select 'True' to enable CRT H1 test", group="Settings", inline="1")
tf = input.timeframe('60', title="Time", group="Settings", inline = "1")
green = input.color(#02fc7f, title="Green", group="Settings", inline = "1")
red = input.color(#fd0901, title="Red", group="Settings", inline = "1")

//logic erc
check_large_candle_only = input.bool(true, title="Only check big candles?", tooltip="Select 'true' to check only large candles")
max_wick_ratio = input.float(0.25, title="Maximum candle wick ratio (compared to the entire candle)", minval=0.01, maxval=1, step=0.01, tooltip="Apply when testing large candles.")
///

// Higher Timeframe Check
isHigherTimeframe = (timeframe.period == tf)

// CRT hour
hourEST1 = 6
hourEST2 = 10
hourEST3 = 14

isTargetCandle = enable_crt_h1_check and (hour(time) == hourEST1 or hour(time) == hourEST2 or hour(time) == hourEST3)

// Variables to Store High, Low, and Index
var float crtHigh = na
var float crtLow = na
var int crtIndex = na

if (isTargetCandle and isHigherTimeframe and barstate.isconfirmed)
    crtHigh := high
    crtLow := low
    crtIndex := bar_index

if (not na(crtHigh) and bar_index == crtIndex + 1)
    if (low < crtHigh and high > crtHigh and close < crtHigh and barstate.isconfirmed)
        line.new(x1=crtIndex, y1=crtHigh, x2=bar_index, y2=crtHigh, color=green, width=2, extend=extend.none)
        alert("High CRT sweep!  " + "\nMã:" + syminfo.ticker + " " + timeframe.period + "\nAbout LTF wait for confirmation to place order", alert.freq_once_per_bar)

if (not na(crtLow) and bar_index == crtIndex + 1)
    if (high > crtLow and low < crtLow and close > crtLow and barstate.isconfirmed)
        line.new(x1=crtIndex, y1=crtLow, x2=bar_index, y2=crtLow, color=red, width=2, extend=extend.none)
        alert("Low CRT sweep!  " + "\nMã:" + syminfo.ticker + " " + timeframe.period + "\nAbout LTF wait for confirmation to place order", alert.freq_once_per_bar)

barcolor(isTargetCandle and isHigherTimeframe ? color.new(color.red, 35) : na)
// Function

// Calculate the length of the candle body and wick
body_size = math.abs(close - open)
upper_wick = high - math.max(open, close)
lower_wick = math.min(open, close) - low
total_wick_size = upper_wick + lower_wick
total_candle_size = high - low

// Conditions to determine large candles
is_large_candle = (total_wick_size / total_candle_size) <= max_wick_ratio

// Candle test condition
should_check = check_large_candle_only ? is_large_candle : true

// Color the large candle if testing a large candle
barcolor(check_large_candle_only and is_large_candle ? (close > open ? color.green : color.red) : na)

// Variable to store the high/low price and index of the candle being tested
var float crtHighs = na
var float crtLows = na
var int crtIndexs = na

// Save the price of the current candle if the test condition is met
if (should_check and barstate.isconfirmed)
    crtHighs := high
    crtLows := low
    crtIndexs := bar_index

//draw line
if (not na(crtHighs) and bar_index == crtIndexs + 1)
    if (low < crtHighs and high > crtHighs and close < crtHighs and barstate.isconfirmed and close < open)
        line.new(x1=crtIndexs, y1=crtHighs, x2=bar_index, y2=crtHighs, color=color.new(color.green, 0), width=2, extend=extend.none)
        alert("Mức cao của nến CRT bị quét!  " + "\nMã:" + syminfo.ticker + " " + timeframe.period + "\nAbout LTF wait for confirmation to place order", alert.freq_once_per_bar)

if (not na(crtLows) and bar_index == crtIndexs + 1)
    if (high > crtLows and low < crtLows and close > crtLows and barstate.isconfirmed and close> open)
        line.new(x1=crtIndexs, y1=crtLows, x2=bar_index, y2=crtLows, color=color.new(color.red, 0), width=2, extend=extend.none)
        alert("Mức thấp của nến CRT bị quét!  " + "\nMã:" + syminfo.ticker + " " + timeframe.period + "\nAbout LTF wait for confirmation to place order", alert.freq_once_per_bar)
// Function to create and manage boxes for HTF Candles
type Candle
    float o
    float c
    float h
    float l
    int o_time
    int o_idx
    int c_idx
    int h_idx
    int l_idx
    string dow
    box body
    line wick_up
    line wick_down
    label dow_label

type CandleSettings
    bool show
    string htf
    int max_display

type Settings
    color bull_body
    color bull_border
    color bull_wick
    color bear_body
    color bear_border
    color bear_wick
    int offset
    int buffer
    int htf_buffer
    int width

type CandleSet
    array<Candle> candles
    CandleSettings settings

type Helper
    string name = 'Helper'
Settings settings = Settings.new()

var CandleSettings SettingsHTF3 = CandleSettings.new()
var array<Candle> candles_3 = array.new<Candle>(0)
var CandleSet htf3 = CandleSet.new()
htf3.settings := SettingsHTF3
htf3.candles := candles_3
htf3.settings.show              := input.bool(true, 'HTF Candle', inline = 'htf3')
htf_3                           = input.timeframe('60', '', inline = 'htf3')
htf3.settings.htf := htf_3
htf3.settings.max_display       := input.int(10, '', inline = 'htf3')
settings.bull_body              := color.green
settings.bear_body              := color.red
settings.bull_border            := color.black
settings.bull_wick              := color.black
settings.bear_wick              := color.black
settings.offset                 := 10
settings.buffer                 := 1
settings.htf_buffer             := 10
settings.width                  := 2

Helper helper = Helper.new()
color color_transparent = #ffffff00

method HTFEnabled(Helper helper) =>
    helper.name := 'HTFEnabled'
    int enabled = 0
    enabled := enabled + (htf3.settings.show ? 1 : 0)
    enabled

method CandleSetHigh(Helper helper, array<Candle> candles, float h) =>
    helper.name := 'CandlesSetHigh'
    float _h = h
    if array.size(candles) > 0
        for i = 0 to array.size(candles) - 1 by 1
            Candle c = array.get(candles, i)
            if c.h > _h
                _h := c.h
                _h
    _h

method CandleSetLow(Helper helper, array<Candle> candles, float l) =>
    helper.name := 'CandlesSetLow'
    float _l = l
    if array.size(candles) > 0
        for i = 0 to array.size(candles) - 1 by 1
            Candle c = array.get(candles, i)
            if c.l < _l
                _l := c.l
                _l
    _l

method CandlesHigh(Helper helper, array<Candle> candles) =>
    helper.name := 'CandlesHigh'
    h = 0.0
    int cnt = 0
    int last = helper.HTFEnabled()

    if array.size(candles) > 0
        for i = 0 to array.size(candles) - 1 by 1
            Candle c = array.get(candles, i)
            if c.h > h
                h := c.h
    h

method CandlesLow(Helper helper, array<Candle> candles, float h) =>
    helper.name := 'CandlesLow'
    l = h
    int cnt = 0
    int last = helper.HTFEnabled()

    if array.size(candles) > 0
        for i = 0 to array.size(candles) - 1 by 1
            Candle c = array.get(candles, i)
            if c.l < l
                l := c.l
    l

method Reorder(CandleSet candleSet, int offset) =>
    size = candleSet.candles.size()
    if size > 0
        for i = size - 1 to 0 by 1
            Candle candle = candleSet.candles.get(i)
            t_buffer = offset + (settings.width + settings.buffer) * (size - i - 1)
            box.set_left(candle.body, bar_index + t_buffer)
            box.set_right(candle.body, bar_index + settings.width + t_buffer)
            line.set_x1(candle.wick_up, bar_index + settings.width / 2 + t_buffer)
            line.set_x2(candle.wick_up, bar_index + settings.width / 2 + t_buffer)
            line.set_x1(candle.wick_down, bar_index + settings.width / 2 + t_buffer)
            line.set_x2(candle.wick_down, bar_index + settings.width / 2 + t_buffer)

    top = 0.0
    bottom = 0.0
    left = bar_index + offset + (settings.width + settings.buffer) * (size - 1) / 2

method Monitor(CandleSet candleSet) =>
    HTFBarTime = time(candleSet.settings.htf, 'america/New_York')
    isNewHTFCandle = ta.change(HTFBarTime) > 0
    if isNewHTFCandle
        Candle candle = Candle.new()
        candle.o := open
        candle.c := close
        candle.h := high
        candle.l := low
        candle.o_time := time
        candle.o_idx := bar_index
        candle.c_idx := bar_index
        candle.h_idx := bar_index
        candle.l_idx := bar_index
        candle.dow := switch
            =>
                ''
        log.info('dow: {1} |{0}|', candle.dow, candleSet.settings.htf)
        bull = candle.c > candle.o
        // Kiểm tra thời gian và thiết lập màu sắc
        isSpecialTime = hour == 6 or hour == 10 or hour == 14
        bodyColor = isSpecialTime ? color.new(color.purple, 0) : (bull ? settings.bull_body : settings.bear_body)
        borderColor = isSpecialTime ? color.purple : (bull ? settings.bull_border : settings.bear_border)
        wickColor = isSpecialTime ? color.purple : (bull ? settings.bull_wick : settings.bear_wick)
        
        candle.body := box.new(bar_index, math.max(candle.o, candle.c), bar_index + 2, math.min(candle.o, candle.c), borderColor, 1, bgcolor = bodyColor)
        candle.wick_up := line.new(bar_index + 1, candle.h, bar_index, math.max(candle.o, candle.c), color = wickColor)
        candle.wick_down := line.new(bar_index + 1, math.min(candle.o, candle.c), bar_index, candle.l, color = wickColor)
        candleSet.candles.unshift(candle)
        if candleSet.candles.size() > candleSet.settings.max_display
            Candle delCandle = array.pop(candleSet.candles)
            box.delete(delCandle.body)
            line.delete(delCandle.wick_up)
            line.delete(delCandle.wick_down)
            delCandle.dow_label.delete()
    candleSet

method Update(CandleSet candleSet, int offset) =>
    if candleSet.candles.size() > 0
        Candle candle = candleSet.candles.first()
        candle.h_idx := high > candle.h ? bar_index : candle.h_idx
        candle.h := high > candle.h ? high : candle.h
        candle.l_idx := low < candle.l ? bar_index : candle.l_idx
        candle.l := low < candle.l ? low : candle.l
        candle.c := close
        candle.c_idx := bar_index
        bull = candle.c > candle.o
        box.set_top(candle.body, candle.o)
        box.set_bottom(candle.body, candle.c)
        box.set_bgcolor(candle.body, bull ? settings.bull_body : settings.bear_body)
        box.set_border_color(candle.body, bull ? settings.bull_border : settings.bear_border)
        line.set_color(candle.wick_up, bull ? settings.bull_wick : settings.bear_wick)
        line.set_color(candle.wick_down, bull ? settings.bull_wick : settings.bear_wick)
        line.set_y1(candle.wick_up, candle.h)
        line.set_y2(candle.wick_up, math.max(candle.o, candle.c))
        line.set_y1(candle.wick_down, candle.l)
        line.set_y2(candle.wick_down, math.min(candle.o, candle.c))
        if barstate.isrealtime or barstate.islast
            candleSet.Reorder(offset)
    candleSet

int cnt = 0
int last = helper.HTFEnabled()
int offset = settings.offset
if htf3.settings.show
    htf3.Monitor().Update(offset)
    cnt := cnt + 1
    offset := offset + (cnt > 0 ? htf3.candles.size() * settings.width + (htf3.candles.size() > 0 ? (htf3.candles.size() - 1) * settings.buffer : 0) + settings.htf_buffer : 0)
    offset


 